home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CICA 1993 April
/
CICA MS Windows - April 1993.iso
/
unzipped
/
programr
/
vbasic
/
huge2
/
hugearr.c
< prev
next >
Wrap
Text File
|
1992-02-23
|
21KB
|
513 lines
/************************************************************************
* *
* HUGEARR.DLL *
* *
* Huge array support for Microsoft Visual Basic *
* *
* By Mike Warning *
* *
* HugeSave and HugeLoad *
* *
* By Harry JF Wykes - End User Computing Limited *
* *
************************************************************************/
#include <memory.h>
#include <windows.h>
#include "hugearr.h"
HANDLE hLocalMem; // handle to local memory
int NumArrays; // total number of arrays
/************************************************************************
* LibMain - *
* Standard DLL constructor. Allocates all of local heap to store *
* array descriptors and then set the total number of arrays possible. *
************************************************************************/
int FAR pascal
LibMain(HANDLE hModule, WORD wDataSeg, WORD cbHeapSize, LPSTR lpszCmdLine)
{
if (cbHeapSize > 0)
UnlockData(0);
// Allocate memory for array descrips.
hLocalMem = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT,
LocalCompact((WORD) 65500));
if (hLocalMem == NULL)
return 0; // Something happened, bomb out
// calc total number of arrays
NumArrays = (int) (LocalSize(hLocalMem) / sizeof(struct ArrayDesc));
return (1);
}
/************************************************************************
* WEP - *
* Standard DLL destructor. Free up local memory and quit. *
************************************************************************/
int FAR pascal WEP(int bSystemExit)
{
LocalFree(hLocalMem);
return (1);
}
/************************************************************************
* HugeDim - *
* Dimensions a new array. The size of the array is *
* (recsize * ubound+1). Recsize is the size in bytes of each element in *
* the array and ubound is the upper bound of the array. All arrays have *
* a lower bound of 0. *
* *
* Note: If total size of the array is greater than 64k, recsize should *
* be an integer power of two (1,2,4,8,16,etc.) Otherwise, the *
* huge pointers will not be added correctly. *
************************************************************************/
int FAR pascal HugeDim(int recsize, long ubound)
{
int hArray; // handle to array to dimension
pDescrip pArray; // pointer to array descriptor
int ret; // return value from HugeAlloc
pArray = (pDescrip) LocalLock(hLocalMem); // find a free array
if ((hArray = GetFreeArray(pArray)) == HA_TOMANYARRAYS) {
LocalUnlock(hLocalMem); // couldn't find one,
return (HA_TOMANYARRAYS); // return error.
}
// allocate new array
ret = HugeAlloc(pArray + hArray, recsize, ubound, FALSE);
LocalUnlock(hLocalMem);
if (ret < 0) // if an error occured during alloc
return (ret); // return the error, else
else
return (hArray); // return the handle to the array
}
/************************************************************************
* HugeRedim - *
* Redimenions the given array to have the new 'ubound'. The old *
* recsize is kept. All data in the array is preserved and any new data *
* (created by expanding the array) is initialized to 0. *
* *
* Note: The recsize must be an integer power of two if the total array *
* size is greater than 64k. *
************************************************************************/
int FAR pascal HugeRedim(int hArray, long ubound)
{
pDescrip pArray; // pointer to array desciptor
register ret; // return code of HugeAlloc
if (hArray < 0 | hArray >= NumArrays)
return (HA_BADARRAY); // illegal array handle
pArray = (pDescrip) LocalLock(hLocalMem) + hArray;
if (pArray -> handle != NULL) // reallocate array
ret = HugeAlloc(pArray, pArray -> recsize, ubound, TRUE);
else
ret = HA_BADARRAY; // array has never been allocated
LocalUnlock(hLocalMem);
return (ret);
}
/********************************************************************
* GetFreeArray - *
* Searches the array descriptor table looking for a free entry. *
* It returns the index into the table if an entry is free or *
* HA_TOMANYARRAYS otherwise. pArray is the pointer to the start of *
* the table. *
********************************************************************/
int GetFreeArray(pDescrip pArray)
{
int i = 0;
// loop until found or out of entries
while ((i < NumArrays) && (pArray -> handle != NULL)) {
++pArray;
++i;
}
if (i == NumArrays) // didn't find a spot
return (HA_TOMANYARRAYS);
return (i); // found one, return index to it
}
/********************************************************************
* GetHugeEl - *
* Retrieves an element of the array storing it into the buffer *
* pointed to by 'buffer'. hArray is the index into the descriptor *
* table of the array, element is the element to get. *
* *
* NOTE: there is absolutely no type checking done on the buffer. *
* It is up to the programmer to make sure it points to the *
* correct data type. *
********************************************************************/
int FAR pascal GetHugeEl(int hArray, long element, BYTE FAR *buffer)
{
BYTE _huge *ptr; // pointer to array element
pDescrip pArray; // pointer to array descriptor
if (hArray < 0 || hArray >= NumArrays)
return (HA_BADARRAY); // illegal array handle
// point to proper descriptor
pArray = (pDescrip) LocalLock(hLocalMem) + hArray;
if (pArray -> handle == NULL) {
LocalUnlock(hLocalMem);
return (HA_BADARRAY); // array hasn't been allocated
}
if ((pArray -> ubound < element) || (element < 0)) {
LocalUnlock(hLocalMem);
return (HA_SUBSCRIPT); // subscript out of range
}
// calculate pointer to element
ptr = (BYTE _huge *) GlobalLock(pArray -> handle);
ptr = ptr + element * pArray->recsize;
_fmemcpy(buffer, ptr, pArray -> recsize); // copy data
GlobalUnlock(pArray -> handle);
LocalUnlock(hLocalMem);
return (HA_OK);
}
/********************************************************************
* SetHugeEl - *
* Sets the value of an array element. This routine is exactly *
* the same as 'GetHugeEl' except that the memory copy is resversed. *
********************************************************************/
int FAR pascal SetHugeEl(int hArray, long element, BYTE FAR *buffer)
{
BYTE _huge *ptr; // pointer to array element
pDescrip pArray; // pointer to array descriptor
if (hArray < 0 || hArray >= NumArrays)
return (HA_BADARRAY); // illegal array handle
// point to proper descriptor
pArray = (pDescrip) LocalLock(hLocalMem) + hArray;
if (pArray -> handle == NULL) {
LocalUnlock(hLocalMem);
return (HA_BADARRAY); // array hasn't been allocated
}
if ((pArray -> ubound < element) || (element < 0)) {
LocalUnlock(hLocalMem);
return (HA_SUBSCRIPT); // subscript out of range
}
// calculate pointer to element
ptr = (BYTE _huge *) GlobalLock(pArray -> handle);
ptr = ptr + element * pArray->recsize;
_fmemcpy(ptr, buffer, pArray -> recsize); // copy data
GlobalUnlock(pArray -> handle);
LocalUnlock(hLocalMem);
return (HA_OK);
}
/********************************************************************
* HugeErase - *
* Deletes an array and marks it as free in the descriptor table. *
* 'hArray' is the array to erase. *
********************************************************************/
int FAR pascal HugeErase(int hArray)
{
pDescrip pArray; // pointer to array descriptor
if (hArray < 0 || hArray >= NumArrays)
return (HA_BADARRAY); // illegal array handle
pArray = (pDescrip) LocalLock(hLocalMem) + hArray;
if (pArray -> handle == NULL) {
LocalUnlock(hLocalMem);
return (HA_BADARRAY); // array hasn't been allocated yet
}
GlobalFree(pArray -> handle); // free the memory
pArray -> handle = NULL;
LocalUnlock(hLocalMem);
return (HA_OK);
}
/********************************************************************
* NumHugeArrays - *
* Returns the number of free entries in the array descriptor table*
********************************************************************/
int FAR pascal NumHugeArrays(void)
{
pDescrip pArray; // pointer to current descriptor
int num, i; // number free so far
pArray = (pDescrip) LocalLock(hLocalMem);
for (i = 0, num = 0; i < NumArrays; i++, pArray++)
if (pArray -> handle == NULL)
++num;
LocalUnlock(hLocalMem);
return (num);
}
/********************************************************************
* HugeUbound - *
* Returns the upper bound of a given array *
********************************************************************/
long FAR pascal HugeUbound(int hArray)
{
pDescrip pArray; // pointer to array descriptor
long ubound; // upper bound of array
if (hArray < 0 || hArray >= NumArrays)
return (HA_BADARRAY); // illegal array handle
pArray = (pDescrip) LocalLock(hLocalMem) + hArray;
if (pArray -> handle == NULL) {
LocalUnlock(hLocalMem);
return (HA_BADARRAY); // array hasn't been allocated yet
}
ubound = pArray -> ubound;
LocalUnlock(hLocalMem);
return (ubound);
}
/********************************************************************
* HugeInt - *
* Same as GetHugeEl except that it explicitly returns an integer. *
* Use this function when you are in an expression such as: *
* i% = 5 * HugeInt(4, 5) *
* *
* NOTE: Because the user could store anything in the array element, *
* they will not know if the value returned is a real value or *
* if an error occured. Use GetHugeEl if the error code must *
* be checked. *
********************************************************************/
int FAR pascal HugeInt(int hArray, long element)
{
int retval;
GetHugeEl(hArray, element, (BYTE FAR *) &retval);
return (retval);
}
/********************************************************************
* HugeLong - *
* Returns an element of a long integer array. (re. HugeInt) *
********************************************************************/
long FAR pascal HugeLong(int hArray, long element)
{
long retval;
GetHugeEl(hArray, element, (BYTE FAR *) &retval);
return (retval);
}
/********************************************************************
* HugeSingle - *
* Returns an element of a single precesion array. (re. HugeInt) *
********************************************************************/
float FAR pascal HugeSingle(int hArray, long element)
{
float retval;
GetHugeEl(hArray, element, (BYTE FAR *) &retval);
return (retval);
}
/********************************************************************
* HugeDouble - *
* Returns an element of a double precesion array. (re. HugeInt) *
********************************************************************/
double FAR pascal HugeDouble(int hArray, long element)
{
double retval;
GetHugeEl(hArray, element, (BYTE FAR *) &retval);
return (retval);
}
/********************************************************************
* HugeCurrency - *
* Returns an element of a currency array. (re. HugeInt) *
********************************************************************/
currency FAR pascal HugeCurrency(int hArray, long element)
{
return((currency) HugeDouble(hArray, element));
}
/********************************************************************
* HugeAlloc - *
* Allocates (or reallocates) global memory for an array. The size *
* of the array is recsize * (ubound + 1) bytes. The information *
* for the array is stored in the array descriptor pointed to by *
* 'pArray'. *
* *
* Note: See HugeDim for a discussion on array size limitations. *
********************************************************************/
int HugeAlloc(pDescrip pArray,int recsize,long ubound, BOOL realloc)
{
HANDLE handle; // temp handle for alloc
++ubound; // ubound = #elements - 1
if (recsize * ubound > 0xffff) // is size integer power two?
if ((recsize <= 0) || (((recsize - 1) & recsize) != 0))
return (HA_BADELEMENTSIZE);
if (realloc) // allocate array
handle = GlobalReAlloc(pArray -> handle, recsize * ubound,
GMEM_MOVEABLE || GMEM_ZEROINIT);
else
handle = GlobalAlloc(GMEM_MOVEABLE || GMEM_ZEROINIT, recsize * ubound);
if (handle == NULL)
return (HA_OUTOFMEMORY); // out of memory
pArray -> handle = handle; // save new handle
pArray -> recsize = recsize; // record element size
pArray -> ubound = ubound - 1;
return (HA_OK);
}
/********************************************************************
* HugeSave - Saves the specified number of elements to a file *
* Returns the number of items saved. *
* *
* NB! HugeSave does not Erase the Huge Array. *
********************************************************************/
long FAR pascal HugeSave(int hArray, long nelements, int OutLen, LPSTR FileSpec)
{
int hSaveFile; // handle to the save file
BYTE _huge *ptr; // pointer to array element
long element; // element in the huge array
pDescrip pArray; // pointer to array descriptor
if (hArray < 0 || hArray >= NumArrays)
return (HA_BADARRAY); // illegal array handle
pArray = (pDescrip) LocalLock(hLocalMem) + hArray;
if (pArray -> handle == NULL)
{
LocalUnlock(hLocalMem);
return (HA_BADARRAY); // array hasn't been allocated yet
}
if ((pArray -> ubound < nelements) || (nelements < 0))
{
LocalUnlock(hLocalMem);
return (HA_SUBSCRIPT); // subscript out of range
}
// Open the file
hSaveFile = _lopen(FileSpec, OF_WRITE);
if(hSaveFile < 0)
{
LocalUnlock(hLocalMem);
return HA_FILEOPENERROR;
}
for(element = 0L; element < nelements; element++)
{
// calculate pointer to element
ptr = (BYTE _huge *) GlobalLock(pArray -> handle);
ptr = ptr + element * pArray->recsize;
// Write out the record
if(_lwrite(hSaveFile, ptr, OutLen) < 0)
{
GlobalUnlock(pArray -> handle);
LocalUnlock(hLocalMem);
_lclose(hSaveFile);
return HA_FILEWRITEERROR;
}
GlobalUnlock(pArray -> handle);
}
// Wrap up and return
_lclose(hSaveFile);
LocalUnlock(hLocalMem);
return(element);
}
/********************************************************************
* HugeLoad - Loads a Huge Array from the specified file *
* Returns the number of elements loaded *
* *
* NB! The array must have been allocated and be of sufficient *
* NB! size to hold the array. *
********************************************************************/
long FAR pascal HugeLoad(int hArray, int InLen, LPSTR FileSpec)
{
int BytesRead; // number of bytes read from the file
int hLoadFile; // handle to the save file
BYTE _huge *ptr; // pointer to array element
long element; // element in the huge array
pDescrip pArray; // pointer to array descriptor
if (hArray < 0 || hArray >= NumArrays)
return (HA_BADARRAY); // illegal array handle
pArray = (pDescrip) LocalLock(hLocalMem) + hArray;
if (pArray -> handle == NULL)
{
LocalUnlock(hLocalMem);
return (HA_BADARRAY); // array hasn't been allocated yet
}
// Open the file
if((hLoadFile = _lopen(FileSpec, OF_READ)) < 0)
{
LocalUnlock(hLocalMem);
return HA_FILEOPENERROR;
}
for(element = 0L; element < pArray -> ubound ; element++)
{
// calculate pointer to element
ptr = (BYTE _huge *) GlobalLock(pArray -> handle);
ptr = ptr + element * pArray->recsize;
// Read the record
BytesRead = _lread(hLoadFile, ptr, InLen);
if(BytesRead < 0)
{
GlobalUnlock(pArray -> handle);
LocalUnlock(hLocalMem);
_lclose(hLoadFile);
return HA_FILEREADERROR;
}
if(BytesRead == 0)
{
GlobalUnlock(pArray -> handle);
break;
}
GlobalUnlock(pArray -> handle);
}
// Wrap up and return
_lclose(hLoadFile);
LocalUnlock(hLocalMem);
return(element);
}